#include <my_header.h>

/* Usage:  */
int main(void){                                  
    char *ip = "192.168.229.128";
    char *port = "8080";

    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(socket_fd, -1, "socket");

    struct sockaddr_in sockaddr;
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(atoi(port));
    sockaddr.sin_addr.s_addr = inet_addr(ip);

    int res_conn = connect(socket_fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
    ERROR_CHECK(res_conn, -1, "connect");

    // 从标准输入读取要下载的文件名
    char file_name[60] = { 0 };
    read(STDIN_FILENO, file_name, sizeof(file_name));
    int name_len = strlen(file_name) -1;
    // 发送给服务端
    send(socket_fd, &name_len, sizeof(int), MSG_NOSIGNAL);
    send(socket_fd, file_name, name_len, MSG_NOSIGNAL);
    // 将文件名最后一个字符(换行符)替换为'\0' 使得file_name是一个有效的字符串
    file_name[name_len] = 0;

    // 创建文件并打开  
    int file_fd = open(file_name, O_RDWR | O_CREAT, 0600); // 以读写模式创建文件，权限为0600  
    // 接受大文件 循环接收 写入磁盘文件
    while(1)
    {
        // 接收文件内容的长度  
        int len;  
        // recv第四个参数不加MSG_WAITALL会出现半包问题 即：传输数据过程中可能会发送一半数据，再发送一半
        // int ret_recv = recv(socket_fd, &len, sizeof(int), 0); // 接收文件内容长度  
        int ret_recv = recv(socket_fd, &len, sizeof(int), MSG_WAITALL);
        if(ret_recv == 0)
        {
            // 服务端传输完数据，断开链接
            break;
        }
        char buf[4096] = {0}; // 缓冲区用于接收数据  
        // int ret_recv2 = recv(socket_fd, buf, len, 0);
        int ret_recv2 = recv(socket_fd, buf, len, MSG_WAITALL); // 接收文件内容，按照长度接收  
        if(ret_recv2 == 0)
        {
            // 服务端传完数据，断开连接
            break;
        }
        // 将接收到的内容写入文件  
        write(file_fd, buf, ret_recv); // 将接收到的内容写入文件  
    }
    // 关闭文件描述符和socket  
    close(file_fd); // 关闭文件  
    close(socket_fd); // 关闭socket  
    return 0; // 正常结束  
}

